<?php
/**
 *  Evoca Media Services REST API utility
 *
 *  This a generic PHP class that can make generic authorized calls to Evoca Media Services
 *
 *  Author:Jeff Walter
 *  http://www.evoca.com
 *
 *  This code is free, provided AS-IS with no warranty expressed or implied.  Use at your own risk.
 *
 */

require_once "eac_curl.class.php";

class EMS_util {

	// The API access point URL
	private $EMS_URL = "http://ems.evoca.com/";

	// set to true to echo debug info
	private $_debug = false;

	// your EMS ClientID
	private $clientID = null;

	// your EMS Public Access ID
	private $publicAccessID = null;

	// your EMS Secret Access Key
	private $secretKey = null;

	// embedded metadata names
	var $_embeddedNames = array("title", "description", "createdDate", "duration", "transcription",
		"author", "aliasName", "aliasTo", "privacy", "getCount", "listenCount", "generatedFormats");

	// eac_cURL options
	private $eac_options = null;

	/**
	 * Constructor: Evoca Media Services REST API utility
	 */
	public function EMS_util($inClientID, $inPublicID, $inSecretKey) {
		$this->clientID = $inClientID;
		$this->publicAccessID = $inPublicID;
		$this->secretKey = $inSecretKey;

		// initialize the eac options
		$this->eac_options = array();
		$this->eac_options["CURLOPT_ENCODING"] = "";
	}

	/**
	 * Returns the URL to the Evoca Media Services
	 * 
	 * @return 
	 */
	function getEMS_URL() {
		return $this->EMS_URL;
	}
	
	/**
	 * Generates an authorized url for an EMS resource
	 * 
	 * @return 
	 * @param $resource Object - the resource URL (e.g. /players/audio/flash/playlistDefault/?filter=publish=true&orderBy=publishDate;DESC&maxResults=100)
	 * @param $method Object - GET, PUT, DELETE, HEAD, or POST
	 * @param $contentmd5string Object - the md5sum of the content body
	 * @param $contenttype Object - if there is a content body, the content type
	 * @param $expiration Object - the date or expires string for the request
	 * @param $metadata Object - any metadata parameters you want to send with the object
	 */
	public function ems_authorized_url($resource, $method, $contentmd5string, $contenttype, $expiration, $metadata) {
		$completeURL = $this->ems_complete_url($resource);

		// Add the public access ID
		if(strpos($resource, "&") == false)
			$completeURL = $completeURL . "?EMAAccessKeyID=" . $this->publicAccessID;
		else
			$completeURL = $completeURL . "&EMAAccessKeyID=" . $this->publicAccessID;

		// Add the signature
		$metadatastring = $this->parse_metadata($metadata);
		$signature = $this->get_request_signature($method, $contentmd5string, $contenttype, $expiration, $metadatastring, $resource);
		$completeURL = $completeURL . "&Signature=" . urlencode($signature);

		// Add the expiration
		if($expiration != null)
			$completeURL = $completeURL . "&Expires=" . $expiration;

		return $completeURL;
	}
	
	/**
	 * Makes an authorized GET request
	 * 
	 * @return 
	 * @param $resource Object - the resource URL (e.g. /players/audio/flash/playlistDefault/?filter=publish=true&orderBy=publishDate;DESC&maxResults=100)
	 * @param $metadata Object - an array of any metadata parameters you want to send with the object
	 * @param $dateOrExpiration Object[optional] - the date or expires string for the request
	 */
	public function ems_get($resource, $metadata, $dateOrExpiration = null) {
		if($dateOrExpiration == null)
			$dateOrExpiration = gmdate(DATE_RFC1123);

		$completeURL = $this->ems_complete_url($resource);
		$http = new cURL($this->eac_options);

		$metadatastring = $this->parse_metadata($metadata);
		$signature = $this->get_request_signature("GET", null, null, $dateOrExpiration, $metadatastring, $resource);

		$http->header("Authorization: EMS " . $this->publicAccessID . ":" . $signature);
		$http->header("Date: " . $dateOrExpiration);

		$this->debug_text(print_r($http->getReqHeaders(), true));
		$http->get($completeURL, $this->eac_options);
		return $http;
	}
	
	/**
	 * Generates the "complete" URL for an EMS resource (http://ems.evoca.com/clients/{clientID}/{resource})
	 * 
	 * @return 
	 * @param $resource Object - the resource URL (e.g. /players/audio/flash/playlistDefault/?filter=publish=true&orderBy=publishDate;DESC&maxResults=100)
	 */
	public function ems_complete_url($resource) {
		return $this->EMS_URL . "clients/" . $this->clientID . $resource;
	}
	
	/**
	 * Generates an authorization signature for EMS
	 * 
	 * @return 
	 * @param $verbString Object - GET, PUT, DELETE, HEAD, or POST
	 * @param $contentmd5string Object[optional] - the md5sum of the content body
	 * @param $contenttypestring Object[optional] - if there is a content body, the content type
	 * @param $httpDate Object[optional] - the date or expires string for the request
	 * @param $metadatastring Object[optional] - any metadata parameters you want to send with the object
	 * @param $resource Object - the resource URL (e.g. /players/audio/flash/playlistDefault/?filter=publish=true&orderBy=publishDate;DESC&maxResults=100)
	 */
	public function get_request_signature($verbString, $contentmd5string = "", $contenttypestring = "", $httpDate = null, $metadatastring = "", $resource) {
		$stringToSign = "$verbString\n$contentmd5string\n$contenttypestring\n$httpDate\n$metadatastring$resource";
		$this->debug_text("Signing String: \n$stringToSign");
		$signature = base64_encode(hash_hmac ("sha1", $stringToSign, $this->secretKey, true));
		return $signature;
	}
	
	/**
	 * Takes an associative array of metadata and creates a string compatible for EMS authorization.
	 * 
	 * @return 
	 * @param $metadata Object - associative array of metadata parameters you want to send with the object
	 */
	public function parse_metadata($metadata) {
		$metadatastring = "";

		if (is_array($metadata)) {
			ksort($metadata);

			$this->debug_text("Metadata found.");

			foreach ($metadata as $key => $value) {

				$metadadtaKeyName = "";

				if(in_array($key, $this->_embeddedNames)) {
					$metadataKeyName = "x-ev-";
				}
				else {
					$metadataKeyName = "x-ev-meta-";
				}

				$metadatastring .= $metadataKeyName.$key.":".trim($value)."\n";

				$this->debug_text("Setting $metadataKeyName$key to '$value'");
			}
		}

		return $metadatastring;
	}

	/**
	 * Takes an associative array of key => value pairs and returns a query string from them.
	 * 
	 * @return 
	 * @param $parameter_array Object - associative array of key => value pairs
	 */
	public function generate_query_string($parameter_array) {
		$querystring = "";

		if (is_array($parameter_array)) {
			$i = 0;
			foreach ($parameter_array as $key => $value) {
				if($i == 0)
					$querystring = $querystring . "?";
				else
					$querystring = $querystring . "&";

				$querystring = $querystring . trim($key) . "=" . trim($value);
				$i++;
			}
		}

		return $querystring;
	}
	
	/**
	 * Utility function for constructing signatures
	 * 
	 * @return 
	 * @param $str Object
	 */
	public function hex2b64($str) {
		$raw = '';
		for ($i=0; $i < strlen($str); $i+=2) {
			$raw .= chr(hexdec(substr($str, $i, 2)));
		}
		return base64_encode($raw);
	}
	
	/**
	 * Echoes debug information to the browser.  Set this->debug to false for production use
	 * 
	 * @return 
	 * @param $text Object
	 */
	private function debug_text($text) {
		if ($this->_debug) {
			echo("<br>\n");
			print_r($text);
			echo("<br><br>\n\n");
		}

		return true;
	}
}

?>